package cn.stylefeng.guns.sys.modular.system.service;

import cn.stylefeng.guns.base.auth.context.LoginContextHolder;
import cn.stylefeng.guns.base.pojo.node.LayuiTreeNode;
import cn.stylefeng.guns.base.pojo.node.TreeviewNode;
import cn.stylefeng.guns.base.pojo.node.ZTreeNode;
import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.sys.core.exception.enums.BizExceptionEnum;
import cn.stylefeng.guns.sys.core.properties.ZxUrlConfig;
import cn.stylefeng.guns.sys.core.util.DDUtil;
import cn.stylefeng.guns.sys.core.util.DateUtil;
import cn.stylefeng.guns.sys.modular.rest.service.RestUserService;
import cn.stylefeng.guns.sys.modular.system.db4.service.TeamService;
import cn.stylefeng.guns.sys.modular.system.db5.service.UserDataService;
import cn.stylefeng.guns.sys.modular.system.entity.Dept;
import cn.stylefeng.guns.sys.modular.system.entity.DeptEmp;
import cn.stylefeng.guns.sys.modular.system.entity.Emp;
import cn.stylefeng.guns.sys.modular.system.mapper.DeptEmpMapper;
import cn.stylefeng.guns.sys.modular.system.mapper.DeptMapper;
import cn.stylefeng.guns.sys.modular.system.mapper.EmpMapper;
import cn.stylefeng.guns.sys.modular.system.model.result.DDEmpResult;
import cn.stylefeng.guns.sys.modular.system.util.DDDepartment;
import cn.stylefeng.guns.sys.modular.system.util.ZxUrl;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.reqres.response.SuccessResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;
import cn.stylefeng.roses.kernel.model.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctc.wstx.util.StringUtil;
import com.google.gson.JsonArray;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author stylefeng
 * @since 2018-12-07
 */
@Service
public class DeptService extends ServiceImpl<DeptMapper, Dept> {

    private static final Logger log = LoggerFactory.getLogger(DeptService.class);
    @Resource
    private DeptMapper deptMapper;
    @Resource
    private EmpMapper empMapper;
    @Resource
    private RestUserService restUserService;
    @Resource
    private BtyWxService btyWxService;
    @Resource
    private TeamService teamService;
    @Resource
    private UserDataService userDataService;
    @Resource
    private BtyTxlService btyTxlService;
    @Resource
    private AttendAuditBtyAreaService attendAuditBtyAreaService;
    @Resource
    private EmpService empService;
    @Resource
    private DeptEmpMapper deptEmpMapper;
    @Resource
    private DDUtil dDUtil;
    @Autowired
    private ZxUrlConfig zxUrlConfig;

    private ZxUrl zxUrl;

    /**
     * 新增部门
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:00 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public void addDept(Dept dept) {

        if (ToolUtil.isOneEmpty(dept, dept.getSimpleName(), dept.getFullName(), dept.getPid(), dept.getDescription())) {
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }

        //完善pids,根据pid拿到pid的pids
        this.deptSetPids(dept);

        this.save(dept);
    }

    /**
     * 修改部门
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:00 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public void editDept(Dept dept) {

        if (ToolUtil.isOneEmpty(dept, dept.getDeptId(), dept.getSimpleName(), dept.getFullName(), dept.getPid())) {
            throw new ServiceException(BizExceptionEnum.REQUEST_NULL);
        }

        //完善pids,根据pid拿到pid的pids
        this.deptSetPids(dept);

        this.updateById(dept);
    }

    /**
     * 删除部门
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:16 PM
     */
    @Transactional
    public void deleteDept(Long deptId) {
        Dept dept = deptMapper.selectById(deptId);

        //根据like查询删除所有级联的部门
        List<Dept> subDepts = deptMapper.likePids(dept.getDeptId());

        for (Dept temp : subDepts) {
            this.removeById(temp.getDeptId());
        }

        this.removeById(dept.getDeptId());
    }

    /**
     * 获取ztree的节点列表
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:16 PM
     */
    public List<ZTreeNode> tree() {
        return this.baseMapper.tree();
    }

    /**
     * 获取layuiTree的节点列表
     *
     * @author fengshuonan
     * @Date 2019-8-27 15:23
     */
    public List<LayuiTreeNode> layuiTree() {
        return this.baseMapper.layuiTree();
    }

    /**
     * 获取部門名稱
     */
    public String name(Long deptId) {
        return this.baseMapper.name(deptId);
    }

    /**
     * 获取ztree的节点列表
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:16 PM
     */
    public List<TreeviewNode> treeviewNodes() {
        return this.baseMapper.treeviewNodes();
    }

    /**
     * 获取所有部门列表
     *
     * @author fengshuonan
     * @Date 2018/12/23 5:16 PM
     */
    public Page<Map<String, Object>> list(String condition, Long deptId) {
        Page page = LayuiPageFactory.defaultPage();
        return this.baseMapper.list(page, condition, deptId);
    }

    /**
     * 设置部门的父级ids
     *
     * @author fengshuonan
     * @Date 2018/12/23 4:58 PM
     */
    private void deptSetPids(Dept dept) {
        if (ToolUtil.isEmpty(dept.getPid()) || dept.getPid().equals(0L)) {
            dept.setPid(0L);
            dept.setPids("[0],");
        } else {
            Long pid = dept.getPid();
            Dept temp = this.getById(pid);
            String pids = temp.getPids();
            dept.setPid(pid);
            dept.setPids(pids + "[" + pid + "],");
        }
    }

    /**
     * 钉钉更新部门
     *
     * @return
     * @throws Exception
     */
    @XxlJob("ddgxbmDataJob")
    public ResponseData syncFromDingDing() throws Exception {
        //获取钉钉部门列表
        JSONArray depts = dDUtil.listDepts();
        initPids(depts,1,"[0],[24]");
        List<DDDepartment> list = JSON.parseArray(JSON.toJSONString(depts), DDDepartment.class);
        List<DDDepartment> lists=new ArrayList<>();
        for (int a=0;a<list.size();a++){
            if(!list.get(a).getPids().equals("[0],[24],[529205900]")){
                DDDepartment dept=new DDDepartment();
                dept.setId(list.get(a).getId());
                dept.setName(list.get(a).getName());
                dept.setPids(list.get(a).getPids());
                dept.setParentid(list.get(a).getParentid());
                lists.add(dept);
            }
        }
        JSONArray deptss= JSONArray.parseArray(JSON.toJSONString(lists));
        if (deptss == null) {
            return SuccessResponseData.error("从钉钉获取部门列表报错！");
        }
        //查询pid=0的根节点
        Dept root = this.baseMapper.selectById(24);//24 是根节点
        List<Dept> deptlist = new ArrayList<>();
        Dept d = null;
        QueryWrapper<Dept> q = null;
        for (int i = 0; i < deptss.size(); i++) {
            JSONObject dept = deptss.getJSONObject(i);
            Integer did = (Integer) dept.get("id");
            Integer pid = (Integer) dept.get("parentid");
            String name = (String) dept.get("name");
            System.out.println(name);
            String pids = (String) dept.get("pids");
            Long pidLong = Long.valueOf(pid);
            if(pidLong==1L){
                pidLong = 24L;
            }

            d = new Dept();
            q = new QueryWrapper<Dept>();
            q.eq("dept_id", did);
            //查询是否已存在
            Dept olddept = this.baseMapper.selectOne(q);

            if (olddept != null) {
                if (olddept.getDdInfo().equals(dept.toJSONString())) {//信息没有变化
                    continue;
                } else {
                    d.setExist(true);
                }
            }
            d.setDeptId(Long.valueOf(did));
            d.setPids(pids);
            d.setPid(pidLong);
            d.setDingdingDeptId(Long.valueOf(did));
            d.setCreateTime(new Date());
            d.setCreateUser(Long.parseLong("1"));
            d.setFullName(name);
            d.setSimpleName(name);
            d.setDdInfo(dept.toJSONString());
            deptlist.add(d);
        }
        if(deptlist.size()>0){
            for (Dept dept : deptlist) {
                if (dept.isExist()) {
                    this.updateById(dept);
                } else {
                    this.save(dept);
                }
            }
        }
        return SuccessResponseData.success("同步门店信息成功！");
    }

    public void initPids(JSONArray d,int pid,String pids){
        if(d!=null&&d.size()>=1) {
            for(int i=0;i<d.size();i++){
                JSONObject obj = d.getJSONObject(i);
                Integer did_t = (Integer) obj.get("id");
                Integer pid_t = (Integer) obj.get("parentid");
                if(pid_t==pid){
                    obj.put("pids",pids);
                    initPids(d,did_t,pids+",["+did_t+"]");
                }
            }
        }
    }

    private void setPids(List<Dept> deptlist, Dept dept) {
        //根据pid找上级。直到找到根节点
        boolean b = true;
        String str = "[" + dept.getPid() + "]";
        Dept temp = dept;
        while (b) {
            Dept dd = getPid(deptlist, temp);
            if (dd != null) {
                str = "[" + dd.getPid() + "]," + str;
                if (dd.getPid().longValue() == 0L) {
                    b = false;
                }
                temp = dd;
            } else {
                b = false;
            }
        }
        dept.setPids(str);
    }

    private Dept getPid(List<Dept> deptlist, Dept dept) {
        for (Dept d : deptlist) {
            if (dept.getPid().longValue() == d.getDeptId().longValue()) {
                return d;
            }
        }
        return null;
    }

    private Map<Integer, List<Long>> getDeptEmps() {
        List<DeptEmp> deptEmps = deptEmpMapper.selectAll();
        Map<Integer, List<Long>> map = new HashMap<>();
        for (DeptEmp ed : deptEmps) {
            if (map.containsKey(ed.getEmpId())) {
                map.get(ed.getEmpId()).add(ed.getDeptId());
            } else {
                List<Long> list = new ArrayList<>();
                list.add(ed.getDeptId());
                map.put(ed.getEmpId(), list);
            }
        }
        return map;
    }

    private List<Integer> getDeptEmps(Long dept_id) {
        QueryWrapper q = new QueryWrapper<Dept>();
        q.eq("dept_id", dept_id);
        List<DeptEmp> deptEmps = deptEmpMapper.selectList(q);
        List<Integer> empList = new ArrayList<Integer>();
        for (DeptEmp ed : deptEmps) {
            empList.add(ed.getEmpId());
        }
        return empList;
    }

    /**
     * 钉钉更新员工
     *
     * @return
     * @throws Exception
     */
//    @Async
    @XxlJob("ddgxygDataJob")
    public ResponseData syncUserFromDingDing() throws Exception {
        //获取所有部门
        int size = 0;
        QueryWrapper q = new QueryWrapper();
        List<Dept> deptlist = this.baseMapper.selectList(q);
        for (Dept v : deptlist) {
            if (v.getDeptId() > 24 && v.getDeptId() < 1489817048) {
                size += syncUserFromDDForApp(v);
                Thread.sleep(2000);
            }
        }
        return SuccessResponseData.success("同步" + size + "人");
    }

    private Dept getDept(List<Dept> deptlist, Long did) {
        for (Dept d : deptlist) {
            if (did.longValue() == d.getDeptId().longValue()) {
                return d;
            }
        }
        return null;
    }

    private Emp generateEmp(JSONObject detail) {
        String name = (String) detail.get("name");
        String unionid = (String) detail.get("unionid");
        String userid = (String) detail.get("userid");//userid
        Object hiredDate = detail.get("hiredDate");//入职时间
        JSONArray departments = (JSONArray) detail.get("department");
        String mobile = (String) detail.get("mobile");
        boolean active = (boolean) detail.get("active");
        String jobnumber = (String) detail.get("jobnumber");//员工工号
        JSONArray roles = (JSONArray) detail.get("roles");
        String position = (String) detail.get("position");//职位
        String rzdate = null;
        if (hiredDate != null) {
            Long rztime = (Long) hiredDate;
            rzdate = DateUtil.getDate(rztime);
        }
        String dname = "";
        String qy1 = "";
        String qy2 = "";
        Emp emp = new Emp(unionid, dname, name, ToolUtil.isEmpty(position) ? "员工" : position, rzdate, mobile, qy1, qy2, detail.toJSONString());
        return emp;
    }


    public ResponseData deptSeles() {
        QueryWrapper<Dept> qw = new QueryWrapper<>();
        qw.select("dept_id as deptId", "simple_name as name").ne("pid", 0L);
        List<Map<String, Object>> mapList = baseMapper.selectMaps(qw);
        return SuccessResponseData.success(mapList);
    }

    /**
     * app按部门更新员工
     *
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public int syncUserFromDDForApp(Dept curDept) throws Exception {
        log.info("开始同步部门[" + curDept.getSimpleName() + "]员工列表................................begin");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Date curDate = new Date();
        String bz = sdf.format(curDate);

        //从钉钉获取所有部门员工信息
        List<DDEmpResult>  uidlist= dDUtil.queryDingdingEmpBydeptid(curDept.getDeptId());
        if (uidlist == null || uidlist.isEmpty()) {
            curDept.setVersion(99);
            deptMapper.updateById(curDept);
            return 0;
        }
        //遍历获取员工信息
        QueryWrapper q = null;

        List<Integer> deptList = getDeptEmps(curDept.getDeptId());
        List<Emp> emps = new LinkedList<>();
        int size = 0;
        for (DDEmpResult d:uidlist) {
            //从钉钉获取员工明细信息
            //根据手机号获取员工信息
            String unionid = d.getUnionid();
            boolean isLeader = d.getIsLeader();
            String mobile = d.getMobile();
            if(mobile==null || mobile.equals("")){
                continue;
            }
            boolean active = d.getActive();
            String remark = d.getRemark();
            boolean isAdmin = d.getIsAdmin();
            String avatar = d.getAvatar();
            boolean isBoss = d.getIsBoss();
            String userid =d.getUserid();//userid
            String jobnumber = d.getJobnumber();//userid
            boolean isHide = d.getIsHide();
            Object hiredDate = d.getHiredDate();//入职时间
            String rzdate = null;
            if (hiredDate != null) {
                Long rztime = (Long) hiredDate;
                rzdate = DateUtil.getDate(rztime);
            }

            String name = d.getName();
            String tel = d.getTel();
            String position = d.getPosition();//职位
            String workPlace = d.getWorkPlace();//职位
            String email = d.getEmail();//职位
            Long order =d.getOrder();//职位

            JSONObject extattr = JSON.parseObject(d.getExtattr());
            String dname = null;
            if (extattr != null) {
                dname = extattr.getString("入职餐厅");
            }

            String qy1 = "";
            String qy2 = "";
            q = new QueryWrapper();
            q.eq("tel", mobile);
                Emp emp = empMapper.selectOne(q);
            if (emp == null) {
                q = new QueryWrapper();
                //根据用户标识查询用户可能有两条
                q.eq("bh", userid);
                List<Emp> empList=empMapper.selectList(q);
                //遍历相同用户标识的数据 进行状态修改，修改完状态继续新增
                for (Emp empss:empList) {
                    empss.setStatus("YGZT99");
                    this.empMapper.updateById(empss);
                    //同步所有关联表
                    updateAllPhone(empss.getTel(),mobile);
                }
                emp = new Emp();
                emp.setBh(userid);
                emp.setDm(dname);
                emp.setXm(name);
                emp.setTel(mobile);
                emp.setZw(position);
                emp.setRq(rzdate);
                emp.setDdDetil("");
                emp.setStatus("YGZT02");
                emp.setStatusView("正式员工");
                emp.setOpenid(unionid);
                emps.add(emp);
                emp.setBz(bz);
                this.empMapper.insert(emp);
                size++;
            } else {
                emp.setBh(userid);
                emp.setDm(dname);
                emp.setXm(name);
                emp.setTel(mobile);
                emp.setZw(position);
                emp.setRq(rzdate);
                emp.setOpenid(unionid);
                emp.setDdDetil("");

                emp.setStatusView("正式员工");
                emp.setBz(bz);
                emp.setStatus("YGZT02");
                this.empMapper.updateById(emp);

                q = new QueryWrapper();
                //根据用户标识查询用户可能有两条或多条
                q.eq("bh", userid);
                List<Emp> empList=empMapper.selectList(q);
                //多条中存在相同的手机号 修改一致的状态 修改其他条为99
                for (Emp empsc:empList) {
                    if(!empsc.getTel().equals(mobile)){
                        empsc.setStatus("YGZT99");
                        this.empMapper.updateById(empsc);
                    }
                    //同步所有关联表
                    updateAllPhone(empsc.getTel(),mobile);
                }

            }
            if (!deptList.contains(emp.getId())) {
                DeptEmp de = new DeptEmp(Long.valueOf(curDept.getDeptId()), emp.getBh(), emp.getId());
                de.setDelFlag("0");
                deptEmpMapper.insert(de);
            }
            //生成用户
            empService.generateUserFromEmp("emp",emp.getId()+"",curDept.getDeptId());
        }
        return size;
    }

    public void updateAllPhone(String oldTel,String mobile){
        //同步员工表 更新手机号
        restUserService.updateRestUserPhone(oldTel,mobile);
        //同步管理员表 更新手机号
        btyWxService.updateBtyWxPhone(oldTel,mobile);
        //同步培训表 更新手机号
        teamService.updateTeamMobile(oldTel,mobile);
        //同步小妖表 更新手机号
        userDataService.changeMobile(oldTel,mobile);
        //通讯录表 更新手机号
        btyTxlService.updateBtyTxlYytel(oldTel,mobile);
        //通讯录人员表同步手机号
        btyTxlService.updateLxfs(oldTel,mobile);
        //人事架构表 更新dh
        attendAuditBtyAreaService.updateDh(oldTel,mobile);
        //人事架构表 更新kqdh
        attendAuditBtyAreaService.updateKqDh(oldTel,mobile);
        //人事架构表 更新yydh
        attendAuditBtyAreaService.updateYydhTels(oldTel,mobile);
        //人事架构表 更新dddh
        attendAuditBtyAreaService.updateDddhTels(oldTel,mobile);
        //人事档案表 更新tel
        attendAuditBtyAreaService.updateArchivesTel(oldTel,mobile);
        //畅聊同步钉钉手机号接口接收参数:原手机号 oldPhone 新手机号 newPhone
        zxUrl=new ZxUrl();
        MultiValueMap<String,String> map=new LinkedMultiValueMap<>();
        map.add("oldPhone",oldTel);
        map.add("newPhone",mobile);
        zxUrl.call(zxUrlConfig.getClurl(),map, zxUrlConfig.getClUpdatePhone());
    }

    @Async
    public JSONObject tongbuYonghu(String code) {
        System.out.println("开始同步用户------------------------begin");
        String url = "https://bty-xcx.imugua.tech/interface/interface/public_save.jsp?handle=yonghu_tongbu_dept&code=" + code;

        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Post请求
        HttpPost request = new HttpPost(url);
        request.setHeader("Content-Type", "application/json;charset=utf8");
        // 添加json对象
//        StringEntity entity = new StringEntity(para.toJSONString(), "UTF-8");
//        request.setEntity(entity);
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 执行Post请求
            response = httpClient.execute(request);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, StandardCharsets.UTF_8));
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("开始同步用户------------------------end");
        return null;
    }

    public ResponseData getRegion(Dept dept) {
        QueryWrapper<Dept> qw = new QueryWrapper<>();
        qw.select("dept_id as deptId", "simple_name as name");
        if(dept.getPid() != null){
            qw.eq("pid", dept.getPid());
        }
        if(StringUtils.isNotBlank(dept.getSimpleName())){
            qw.like("simple_name", dept.getSimpleName());
        }
        List<Map<String, Object>> mapList = baseMapper.selectMaps(qw);
        return SuccessResponseData.success(mapList);
    }
}
